'''
Created on Nov 23, 2010

@author: dexen
'''

import sys
import time
import traceback
from StringIO import StringIO

from dexen.system.common.base import BaseSlaveTask
from dexen.system.node.slave.comm import InUnit
from dexen.system.common.meta import JobMeta, TaskMeta
from dexen.system.common.transact import SlaveSendTransact, SlaveRecvTransact



class SlaveTaskExecutor(object):
    def __init__(self, job_meta):
        self.job_meta = job_meta
        self._setup()
        
    def _setup(self):
        job_meta = self.job_meta
        assert isinstance(job_meta, JobMeta)
        job_meta.setup_schema()
        
    def execute(self, unit):
        assert isinstance(unit, InUnit)
        transact = unit.transact
        master_state = unit.master_state
        job_meta = self.job_meta
        assert isinstance(job_meta, JobMeta)
        assert isinstance(transact, SlaveSendTransact)
        task_meta = transact.get_task_meta()
        assert isinstance(task_meta, TaskMeta)
        
        job_meta.setup_env()
        try:
            sys.stdout = StringIO()
            sys.stderr = StringIO()
            slave_task = task_meta.get_obj()
            assert isinstance(slave_task, BaseSlaveTask)
            s_time = time.time()
            out_transact = transact.create_slave_recv_transact()           
            #out_transact = SlaveRecvTransact(transact.id, transact.task_meta, transact.slave_name)
            assert isinstance(out_transact, SlaveRecvTransact)
            inds = slave_task.__execute__(master_state, transact.get_inds())                
            out_transact.set_exec_time(time.time() - s_time)
            out_transact.set_inds(inds)
            out_transact.task_succeeded()
        except:
            out_transact.set_inds([])
            traceback.print_tb(sys.exc_info()[2])
            out_transact.set_err_msg(sys.stderr.getvalue())
            out_transact.task_failed()
        finally:
            out_transact.set_out_msg(sys.stdout.getvalue())
            job_meta.reset_env()
            sys.stderr = sys.__stderr__
            sys.stdout = sys.__stdout__
            #print "Inds type\n", type(out_transact.inds)
            return out_transact

    def get_job_meta(self):
        return self.job_meta
    
    def get_job_id(self):
        job_meta = self.job_meta
        assert isinstance(job_meta, JobMeta)
        return job_meta.get_id()
